import axios from 'axios'
import PendingRequest from './PendingRequest'
import Loading from './Loading'
import Error from './Error'
import Log from './Log'
import { useUserStore } from '@/store/User'
import { IOption, IInstance, IError, IResponse, AxiosInstance, AxiosPromise } from '../types/base'

export default class Request {
	private DefaultConfig: IOption = {}
	private MergeConfig: IOption = {}
	private Instance: IInstance = {}
	private RequestStartTime = 0

	constructor(baseURL = '') {
		this.DefaultConfig = {
			baseURL,
			method: 'GET',
			headers: { 'Content-Type': 'application/json; charset=UTF-8' },
			timeout: 6 * 10 * 1000,
			isRequest_cancel: true,
			loading: true,
			isError: true,
			isFullData: false,
			isLog: true,
		}
	}

	/**
	 * 创建Axios实例
	 *
	 * @param { option:IOption } 	用户自定义配置
	 * @returns { AxiosPromise }    Axios实例
	 * @memberof Request
	 */
	createAxiosInstance(option: IOption = {}): AxiosPromise {
		const instance: AxiosInstance = axios.create()
		const config = { ...this.DefaultConfig, ...option }
		this.MergeConfig = config
		this.Instance = instance
		// 拦截器处理
		this.interceptors(instance)
		// 返回Axios实例
		return instance(config)
	}

	/**
	 * 拦截器处理模块
	 *
	 * @param {axios:AxiosInstance} 实例
	 * @memberof Request
	 */
	interceptors(axios: AxiosInstance) {
		// 请求拦截
		axios.interceptors.request.use(
			(config: IOption) => interceptorsReq(config),
			(error: IError) => interceptorsE(error)
		)

		// 响应拦截
		axios.interceptors.response.use(
			(response: IResponse) => interceptorsRes(response),
			(error: IError) => interceptorsE(error)
		)

		const interceptorsReq = (config: IOption) => {
			this.RequestStartTime = new Date().getTime()
			const { isRequest_cancel } = config

			// 每次请求携带token(根据业务需求修改)
			const token = useUserStore().GET_TOKEN()
			// @ts-ignore 不校验headers是否存在token
			token && (config.headers.token = token)

			// 取消重复请求
			PendingRequest.removePending(config)
			isRequest_cancel && PendingRequest.addPending(config)
			// 显示loading
			Loading.set_loadingInstance_target(config.loading as boolean)
			return config
		}

		const interceptorsRes = async (response: IResponse) => {
			// 响应时间
			const responseTime = new Date().getTime() - this.RequestStartTime
			// 如果接口响应时间过快 会造成loading闪烁的问题，延迟关闭loading
			const { isError, loading, isLog } = response.config
			// 移除请求
			PendingRequest.removePending(response.config)
			// 响应时间少于 1s 延迟loading
			if (responseTime <= 1 * 1000) {
				await this.utils().delay(1000)
			}
			// 关闭loading
			Loading.remove_loadingInstance_target(loading as boolean)
			// 开启错误提示展示
			isError && Error.responseHandle(response)
			// 打印响应日志
			isLog && Log.responseLog(response)
			return response.config.isFullData ? response : response.data
		}

		const interceptorsE = (error: IError) => {
			const { isError, loading, isLog } = this.MergeConfig
			// 关闭loading
			Loading.remove_loadingInstance_target(loading as boolean)
			// 开启错误提示展示
			isError && Error.errorHandle(error)
			// 由于多次请求返回的error没有config信息, 此处挂载mergeConfig
			error.config = { ...this.MergeConfig, ...error.config }
			// // 打印请求错误日志
			isLog && Log.errorLog(error)
			return Promise.reject(error)
		}
	}

	utils() {
		return {
			delay(delayTime: number) {
				return new Promise((resolve, reject) => {
					let timer: NodeJS.Timeout | null = setTimeout(() => {
						timer = null
						resolve(true)
					}, delayTime)
				})
			},
		}
	}
}
